#include <CallBack.h>

// Compile and upload to arduino. Run the serial monitor and type command
// :help;

// Values for initiation of cmd/response interface. 
// After initial boot, id, gid and del are stored in eeprom.
// Change values by command. Make sure each device has a unique id.
String descr="Command/response test program v0.1";
String id="a1";
String gid="a";
int    del=0; //delayed response

// List of commands defined by keyword, funtion pointer, number of arguments 
// and description used in "help" command.
CallBackDef f[] = {
  {(String)"setled",     (FunctionPointer)&setled,    (int)1, (String)":on|off"},
  {(String)"blinkled",   (FunctionPointer)&blinkled,  (int)1, (String)":on|off"},
  {(String)"blinkdelay", (FunctionPointer)&blinkdelay,(int)1, (String)":millis"},
  {(String)"add",        (FunctionPointer)&add,       (int)2, (String)":num1:num2"}
};

// initiate command handler: function array, number of functions and intial values
CallBack cmd(f, sizeof(f) / sizeof(*f), id, gid, descr, del);

int led = 13;
bool blnk = 0;
unsigned long blnkTimer = 0;
int blnkDelay = 500;
int ledStatus = LOW;

void setup() {
  Serial.begin(9600);
  cmd.ok(); // say hello
  pinMode(led, OUTPUT); 
}

void loop() {
  // Don't forget this line. Parse command if serial data is available.
  cmd.cmdCheck();
  
  // Put code here. Use timers instead of delay if possible as not to disrupt
  // command/response interaction with host
  
  if(blnk) {
    if(millis() > (blnkTimer + blnkDelay)) {
      blnkTimer = millis();
      if (ledStatus == LOW) {ledStatus = HIGH;}
      else {ledStatus = LOW;}
      digitalWrite(led, ledStatus);
    }
  }
}


//   --------- command initiated callback functions below ---------
// callback functions all need to be defined void and with String argv
// argument list. The command parser will validate the number of input
// parameters but any additional validation has to be perfomed by each
// callback function. As the argument list is passed as strings, type
// casting to other types is the responsibility of the function.

void setled(String argv[]) {
  String action = argv[0];
  if(action == "on") {
    digitalWrite(led, HIGH);
    cmd.ok();
  } else if (action == "off") {
    digitalWrite(led, LOW);
    cmd.ok();
  } else {
    cmd.nok("Illegal argument");
  }
}

void blinkled(String argv[]) {
  String action = argv[0];
  if(action == "on") {
    blnk = 1;
    blnkTimer = millis();
    cmd.ok();
  } else if (action == "off") {
    blnk = 0;
    cmd.ok();
  } else {
    cmd.nok("Illegal argument");
  }  
}

void blinkdelay(String argv[]) {
  blnkDelay = cmd.stoi(argv[0]);
}

void add(String argv[]) {
  int a = cmd.stoi(argv[0]);
  int b = cmd.stoi(argv[1]);
  cmd.respond(String(a + b));
}
